import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import * as Exceljs from 'exceljs';
import { DataSource, Repository } from 'typeorm';
import { BaseService, IOptions } from 'src/modules/base.service';
import { CreateUserDto, UpdateUserDto } from './user.dto';
import { User } from './user.entity';

@Injectable()
export class UserService extends BaseService {
  module: Repository<User>;
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
    private dataSource: DataSource,
  ) {
    super();
    this.module = usersRepository;
  }

  static getCell(target, key, value) {
    const handler = {
      1: (target, value) => {
        target.user_name = value;
      },
      2: (target, value) => {
        target.nick_name = value;
      },
      3: (target, value) => {
        target.sex = value;
      },
      4: (target, value) => {
        target.roles = value;
      },
      5: (target, value) => {
        target.dept = value;
      },
    };
    handler[key] && handler[key](target, value);
  }

  // 获取详情
  async getOne(options: IOptions = {}): Promise<any> {
    return this['module'].findOne(options);
  }

  async create(user: CreateUserDto): Promise<any> {
    try {
      return await this.usersRepository.save(user);
    } catch (error) {
      if (error.code && error.code === 'ER_DUP_ENTRY') {
        throw new Error('用户名被占用');
      }
      if (error.code && error.code === 'ER_NO_REFERENCED_ROW_2') {
        throw new Error('角色不存在');
      }
    }
  }

  // 用户导入
  async importUser(users: CreateUserDto[]): Promise<any> {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    try {
      for (let i = 0; i < users.length; i++) {
        await this.usersRepository.save(users[i]);
      }
    } catch (error) {
      if (error.code && error.code === 'ER_DUP_ENTRY') {
        throw new Error('用户名被占用');
      }
      if (error.code && error.code === 'ER_NO_REFERENCED_ROW_2') {
        throw new Error('角色不存在');
      }
    }
  }

  async update(user: UpdateUserDto): Promise<any> {
    if (!user.roles || user.roles.length === 0) {
      return await this.usersRepository.save(user);
    }
    try {
      return await this.usersRepository.save(user);
    } catch (error) {
      if (error.code && error.code === 'ER_DUP_ENTRY') {
        throw new Error('用户名被占用');
      }
      if (error.code && error.code === 'ER_NO_REFERENCED_ROW_2') {
        throw new Error('角色不存在');
      }
    }
  }

  // 导入
  async importExcel(file: Express.Multer.File): Promise<any> {
    const { buffer } = file;
    const workbook = new Exceljs.Workbook();
    await workbook.xlsx.load(buffer);
    const worksheet = workbook.getWorksheet(1);
    const result = [];
    worksheet.eachRow((row, rowNumber) => {
      if (rowNumber > 1) {
        const target = {};
        row.eachCell((cell, colNumber) => {
          UserService.getCell(target, colNumber, cell.value);
        });
        result.push(target);
      }
    });
    return result;
  }

  // 导出用户模板
  async exportExcel(data = []): Promise<any> {
    const wb = new Exceljs.Workbook();
    if (data && data.length) {
      for (let i = 0; i < data.length; i++) {
        if (data[i].sheet && data[i].columns && data[i].rows) {
          const ws = wb.addWorksheet(data[i].sheet);
          ws.addTable({
            name: data[i].sheet,
            ref: 'A1',
            style: {
              showRowStripes: true,
            },
            columns: data[i].columns,
            rows: data[i].rows,
          });
          for (let j = 0; j < data[i].columns.length; j++) {
            ws.getColumn(j + 1).alignment = {
              wrapText: true,
              indent: 1,
              vertical: 'middle',
              horizontal: 'center',
            };
            Object.keys(data[i].columns[j]).forEach((key) => {
              ws.getColumn(j + 1)[key] = data[i].columns[j][key];
            });
          }
          ws.getRow(1).font = { name: 'Arial', size: 12, bold: true };
        }
      }
    }

    // 写入 buffer
    const buffer = await wb.xlsx.writeBuffer();
    return buffer;
  }
}
